#include "stdafx.h"
#include "primitive_datatypes.h"
#include "Vector.h"
#include "Matrix.h"

//##########################################################
Mat4x4::Mat4x4() :
	_11(0)	,_12(0)	,_13(0)	,_14(0),
	_21(0)	,_22(0)	,_23(0)	,_24(0),
	_31(0)	,_32(0)	,_33(0)	,_34(0),
	_41(0)	,_42(0)	,_43(0)	,_44(0)
{
}
//##########################################################
Mat4x4::Mat4x4( Const Number* axData){
	memcpy(&_11,axData,sizeof(Mat4x4));
}
//##########################################################
Mat4x4::Mat4x4( Const Mat4x4& other){
	memcpy(&_11, &other,sizeof(Mat4x4));
}
//##########################################################
Mat4x4::Mat4x4( Number _11, Number _12, Number _13, Number _14,
		 Number _21, Number _22, Number _23, Number _24,
		 Number _31, Number _32, Number _33, Number _34,
		 Number _41, Number _42, Number _43, Number _44 ):
	_11(_11),_12(_12),_13(_13),_14(_14),
	_21(_21),_22(_22),_23(_23),_24(_24),
	_31(_31),_32(_32),_33(_33),_34(_34),
	_41(_41),_42(_42),_43(_43),_44(_44)
{
}
//##########################################################
Inline
Mat4x4& Mat4x4::operator = (Const Mat4x4& old){
	memcpy(&_11, &old,sizeof(Mat4x4));
	return *this;
}
//##########################################################
Inline
Number& Mat4x4::operator () ( Int Row, Int Col ){
	assert(Row >= 0 && Col >= 0 && Row < 4 && Col < 4);
	return this->_m[Row][Col];
}
//##########################################################
Inline
Number  Mat4x4::operator () ( Int Row, Int Col ) Const{
	assert(Row >= 0 && Col >= 0 && Row < 4 && Col < 4);
	return this->_m[Row][Col];
}
//##########################################################
Inline
Mat4x4::operator Number* (){
	return static_cast<Number*>( &_11);
}
//##########################################################
Inline
Mat4x4::operator Const Number* () Const{
	return static_cast<Const Number*>( &_11);
}
//##########################################################
Inline
Mat4x4&	Mat4x4::operator *= ( Const Mat4x4& other){
	Mat4x4 temp;

	for(Int i = 0; i < 4; i++)
		for(Int j = 0; j < 4; j++)
			for(Int k = 0; k < 4; k++)
				temp._m[i][j] += this->_m[i][k] * other._m[k][j];

	this->operator=(temp);

	return *this;
}
//##########################################################
Inline
Mat4x4&	Mat4x4::operator += ( Const Mat4x4& other){
	for(Int i = 0; i  < 16; i++)
		this->_data[i] += other._data[i];

	return *this;
}
//##########################################################
Inline
Mat4x4&	Mat4x4::operator -= ( Const Mat4x4& other){
	for(Int i = 0; i < 16; i++)
		this->_data[i] -= other._data[i];

	return *this;
}
//##########################################################
Inline
Mat4x4&	Mat4x4::operator *= ( Number scalar){
	for(Int i = 0; i < 16; i++)
		this->_data[i] *= scalar;

	return *this;
}
//##########################################################
Inline
Mat4x4&	Mat4x4::operator /= ( Number scalar){
	Number invScalar = 1 / scalar;

	this->operator*=(invScalar);

	return *this;
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator + () Const{
	return *this;
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator - () Const{
	Mat4x4 mat(*this);
	return mat.negate();
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator * ( Const Mat4x4& other) Const{
	Mat4x4 mat(*this);
	return mat.operator*=(other);
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator + ( Const Mat4x4& other) Const{
	Mat4x4 temp(*this);
	temp.operator+=(other);

	return temp;
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator - ( Const Mat4x4& other) Const{
	Mat4x4 temp(*this);
	temp.operator-=(other);

	return temp;
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator * ( Number scalar) Const{
	Mat4x4 temp(*this);
	temp.operator*=(scalar);

	return temp;
}
//##########################################################
Inline
Mat4x4		Mat4x4::operator / ( Number scalar) Const{
	Mat4x4 temp(*this);
	temp.operator/=(scalar);

	return temp;
}
//##########################################################
Inline
Mat4x4		operator * ( Number scalar, Const Mat4x4& other){
	Mat4x4 mat(other);
	mat.operator*(scalar);
	return mat;
}
//##########################################################
Inline
Bool	Mat4x4::operator == ( Const Mat4x4& other) Const{
	return this->_11 == other._11 && this->_12 == other._12 && this->_13 == other._13 && this->_14 == other._14 &&
			this->_21 == other._21 && this->_22 == other._22 && this->_23 == other._23 && this->_24 == other._24 &&
			this->_31 == other._31 && this->_32 == other._32 && this->_33 == other._33 && this->_34 == other._34 &&
			this->_41 == other._41 && this->_42 == other._42 && this->_43 == other._43 && this->_44 == other._44;
}
//##########################################################
Inline
Bool	Mat4x4::operator != ( Const Mat4x4& other) Const{
	return ! this->operator==(other);
}
//##########################################################
Inline
Mat4x4&	Mat4x4::negate(){
	for(Int i = 0;i < 16; i++)
		this->_data[i] = -this->_data[i];

	return *this;
}
//##########################################################
Inline
Mat4x4		Mat4x4::negated(){
	Mat4x4 mat(*this);
	return mat.negate();
}
//##########################################################
Inline
Mat4x4&	Mat4x4::transpose(){
	Mat4x4 temp;
	for(Int i = 0; i < 4; i++)
		for(Int j = 0; j < 4; j++)
			temp._m[i][j] = this->_m[j][i];

	this->operator=(temp);

	return *this;
}
//##########################################################
Inline
Mat4x4		Mat4x4::transposed(){
	Mat4x4 temp;
	for(Int i = 0; i < 4; i++)
		for(Int j = 0; j < 4; j++)
			temp._m[i][j] = this->_m[j][i];

	return temp;
}
//##########################################################
Mat4x4&	Mat4x4::inverse(){
	return *this;
}
//##########################################################
Inline
Number	Mat4x4::determinat(){
	return (
		((_11 * _22 * _33 * _44) + (_21 * _32 * _43 * _14) + (_31 * _42 * _13 * _24) * (_41 * _12 * _23 * _34)) -
		((_41 * _32 * _23 * _14) + (_31 * _22 * _13 * _44) + (_21 * _12 * _43 * _34) * (_11 * _42 * _33 * _24))
		);
}
//##########################################################
// static functions	########################################
//##########################################################
Inline
void	Mat4x4::Identity(Mat4x4& mat){
	mat._12 = mat._13 = mat._14 = mat._21 = mat._23 = mat._24 = mat._31 = mat._32 = mat._34 = mat._41 = mat._42 = mat._43 = 0.0f;
	mat._11 = mat._22 = mat._33 = mat._44 = 1.0f;
}
//##########################################################
Inline
Mat4x4		Mat4x4::Identity(void){
	return Mat4x4(	1.0f,0.0f,0.0f,0.0f,
				0.0f,1.0f,0.0f,0.0f,
				0.0f,0.0f,1.0f,0.0f,
				0.0f,0.0f,0.0f,0.0f);
}
//##########################################################
Inline
void	Mat4x4::Inverse(Mat4x4& mat){

}
//##########################################################
Inline
void Mat4x4::Translate(Number x, Number y, Number z, Mat4x4& mat){
	Mat4x4::Identity(mat);
	mat._14 = x;
	mat._24 = y;
	mat._34 = z;
}
//##########################################################
Inline
Mat4x4	 Mat4x4::Translate(Number x, Number y, Number z){
	Mat4x4 mat = Mat4x4::Identity();
	mat._14 = x;
	mat._24 = y;
	mat._34 = z;

	return mat;
}
//##########################################################
Inline
void Mat4x4::Translate(Vec3 pos, Mat4x4& mat){
	Mat4x4::Identity(mat);
	mat._14 = pos._x;
	mat._24 = pos._y;
	mat._34 = pos._z;
}
//##########################################################
Inline
Mat4x4	 Mat4x4::Translate(Vec3 pos){
	Mat4x4 mat = Mat4x4::Identity();
	mat._14 = pos._x;
	mat._24 = pos._y;
	mat._34 = pos._z;

	return mat;
}
//##########################################################
Inline
void	Mat4x4::Scale(Number factor,Mat4x4& mat){
	mat._12 = mat._13 = mat._14 = mat._21 = mat._23 = mat._24 = mat._31 = mat._32 = mat._34 = mat._41 = mat._42 = mat._43 = 0.0f;
	mat._11 = mat._22 = mat._33 = factor;
	mat._44 = 1.0f;
}
//##########################################################
Inline
Mat4x4	Mat4x4::Scale(Number factor){
	return Mat4x4(	factor,	0.0f,	0.0f,	0.0f,
				0.0f,	factor,	0.0f,	0.0f,
				0.0f,	0.0f,	factor,	0.0f,
				0.0f,	0.0f,	0.0f,	1.0f);
}
//##########################################################
Inline
void	Mat4x4::Scale(Number factorX, Number factorY, Number factorZ, Mat4x4& mat){
	mat._12 = mat._13 = mat._14 = mat._21 = mat._23 = mat._24 = mat._31 = mat._32 = mat._34 = mat._41 = mat._42 = mat._43 = 0.0f;
	mat._11 = factorX;
	mat._22 = factorY;
	mat._33 = factorZ;
	mat._44 = 1.0f;
}
//##########################################################
Inline
Mat4x4	Mat4x4::Scale(Number factorX, Number factorY, Number factorZ){
	return Mat4x4(	factorX,	0.0f,		0.0f,		0.0f,
				0.0f,		factorZ,	0.0f,		0.0f,
				0.0f,		0.0f,		factorZ,	0.0f,
				0.0f,		0.0f,		0.0f,		1.0f);
}
//##########################################################
Inline
void RotateX(Number angle, Mat4x4& mat){
	mat._11 = 1.0f;		mat._12 = 0.0f;			mat._13 = 0.0f;			mat._14 = 0.0f;
	mat._21 = 0.0f;		mat._22 = cosf(angle);	mat._23 = sinf(angle);	mat._24 = 0.0f;
	mat._31 = 0.0f;		mat._32 = -mat._23;		mat._33 = mat._22;		mat._34 = 0.0f;
	mat._41 = 0.0f;		mat._42 = 0.0f;			mat._43 = 0.0f;			mat._44 = 1.0f;
}
//##########################################################
Inline
Mat4x4	RotateX(Number angle){
	Mat4x4 mat;
	mat._11 = 1.0f;		mat._12 = 0.0f;			mat._13 = 0.0f;			mat._14 = 0.0f;
	mat._21 = 0.0f;		mat._22 = cosf(angle);	mat._23 = sinf(angle);	mat._24 = 0.0f;
	mat._31 = 0.0f;		mat._32 = -mat._23;		mat._33 = mat._22;		mat._34 = 0.0f;
	mat._41 = 0.0f;		mat._42 = 0.0f;			mat._43 = 0.0f;			mat._44 = 1.0f;

	return mat;
}
//##########################################################
Inline
void RotateY(Number angle, Mat4x4& mat){
	mat._11 = 1.0f;		mat._12 = 0.0f;			mat._13 = 0.0f;			mat._14 = 0.0f;
	mat._21 = 0.0f;		mat._22 = cosf(angle);	mat._23 = sinf(angle);	mat._24 = 0.0f;
	mat._31 = 0.0f;		mat._32 = -mat._23;		mat._33 = mat._22;		mat._34 = 0.0f;
	mat._41 = 0.0f;		mat._42 = 0.0f;			mat._43 = 0.0f;			mat._44 = 1.0f;
}
//##########################################################
Inline
Mat4x4	RotateY(Number angle){
}
//##########################################################
Inline
void RotateZ(Number angle, Mat4x4& mat){
}
//##########################################################
Inline
Mat4x4	RotateZ(Number angle){
}
//##########################################################
Inline
void Rotate(Number roll, Number pitch, Number yaw, Mat4x4& mat){
}
//##########################################################
Inline
Mat4x4	Rotate(Number roll, Number pitch, Number yaw){
}
//##########################################################